先建表, CHANNEL_MAP
的索引表示通道 id,這邊暫時用數值 id,因此以陣列方式實現。若為字串 id 則用 Map 表現。
private readonly CHANNEL_MAP = [
[61, 24],
[64, 47],
[63, 4],
[17, 62],
[11, 56],
[43, 23],
[16, 48],
[57, 20],
[20, 10],
[20, 34],
[34, 10],
[57, 10],
[57, 34],
[26, 44],
[7, 31],
[1, 8],
[13, 33],
[15, 5],
[2, 14],
[46, 29],
[25, 51],
[21, 45],
[37, 40],
[12, 22],
[35, 36],
[27, 50],
[32, 54],
[28, 38],
[18, 58],
[42, 53],
[3, 60],
[9, 52],
[59, 6],
[19, 49],
[39, 55],
[41, 30],
];
接著建立反向表,用於查詢某閘門屬於哪個通道。
private readonly REVERSE_CHANNEL_MAP = new Map<number, number>(
this.CHANNEL_MAP.flatMap(([g1, g2], idx) => [
[g1, idx] as const,
[g2, idx] as const,
]),
);
最後實作演算法:
public getChannels(gates: number[]): number[] {
const channels = [];
const candidate = new Set();
for (const gate of gates) {
const channel = this.REVERSE_CHANNEL_MAP.get(gate);
assert(channel);
if (candidate.has(channel)) {
candidate.delete(channel);
channels.push(channel);
} else {
candidate.add(channel);
}
}
return channels;
}
it('getChannels()', () => {
expect(
service.getChannels([
48, 21, 5, 30, 29, 6, 14, 39, 58, 10, 38, 1, 13, 7, 61, 41, 9, 52, 54,
]),
).toEqual([35, 31]);
});
得到結果:
> jest
PASS src/body-graph/body-graph.service.spec.ts
BodyGraphService
✓ getDesignDate() (6 ms)
✓ getDesignDate() (3 ms)
✓ getBodyGraph() (3 ms)
✓ getChannels() (1 ms)
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 1.182 s, estimated 2 s
Ran all test suites.
晚安,瑪卡巴卡。